import requests
import json
import re
import time
import os


def crawl_sina_news_api(url):
    """爬取新浪新闻API数据"""
    # 设置请求头，模拟浏览器访问
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Connection': 'keep-alive',
        'Referer': 'https://news.sina.com.cn/'
    }
    
    try:
        # 发送GET请求获取API数据
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()  # 如果请求不成功则抛出异常
        
        # 提取JSON数据（从jQuery回调中提取）
        content = response.text
        
        # 打印响应内容的前100个字符，帮助调试
        print(f"响应内容前100个字符: {content[:100]}")
        
        try:
            # 首先尝试找到jQuery回调的开始和结束位置
            start_pos = content.find('(')
            end_pos = content.rfind(')')
            
            if start_pos != -1 and end_pos != -1 and start_pos < end_pos:
                # 提取括号内的内容
                json_str = content[start_pos + 1:end_pos]
                
                # 使用更安全的方法解析JSON
                # 新浪API返回的JSON可能包含额外数据，需要手动处理
                
                # 1. 确保JSON字符串以{开始
                if not json_str.strip().startswith('{'):
                    # 如果不是以{开始，尝试找到第一个{
                    brace_start = json_str.find('{')
                    if brace_start != -1:
                        json_str = json_str[brace_start:]
                    else:
                        raise Exception("无法找到JSON对象的开始位置")
                
                # 2. 使用json模块的JSONDecoder手动解析，只解析有效的JSON部分
                decoder = json.JSONDecoder()
                try:
                    # 解析第一个完整的JSON对象
                    data, _ = decoder.raw_decode(json_str)
                    # 成功解析，不需要进一步处理
                    print("成功解析JSON数据")
                except json.JSONDecodeError as e:
                    print(f"JSON解析错误: {e}")
                    # 尝试手动查找有效的JSON对象
                    # 假设JSON对象以{开始，以}结束，并且是平衡的
                    brace_count = 0
                    valid_end = -1
                    
                    for i, char in enumerate(json_str):
                        if char == '{':
                            brace_count += 1
                        elif char == '}':
                            brace_count -= 1
                            if brace_count == 0:
                                valid_end = i
                                break
                    
                    if valid_end != -1:
                        json_str = json_str[:valid_end + 1]
                        print(f"截取后的JSON长度: {len(json_str)}")
                        # 再次尝试解析
                        data = json.loads(json_str)
                    else:
                        raise Exception("无法找到有效的JSON对象结束位置")
            else:
                raise Exception("无法在响应中找到有效的括号对")
        except Exception as e:
            print(f"提取JSON时出错: {e}")
            raise Exception(f"无法从响应中提取有效的JSON数据: {str(e)}")
        
        # 打印提取的JSON字符串的前100个字符，帮助调试
        print(f"提取的JSON前100个字符: {json_str[:100]}")
        print(f"提取的JSON最后100个字符: {json_str[-100:] if len(json_str) > 100 else json_str}")
        
        # 提取新闻列表
        result = {
            'status': data.get('result', {}).get('status', {}),
            'timestamp': data.get('result', {}).get('timestamp', ''),
            'total': data.get('result', {}).get('total', 0),
            'news_list': [],
            'crawl_time': time.strftime('%Y-%m-%d %H:%M:%S')
        }
        
        # 提取新闻列表数据
        news_items = data.get('result', {}).get('data', [])
        for item in news_items:
            news_info = {
                'title': item.get('title', ''),
                'url': item.get('url', ''),
                'wapurl': item.get('wapurl', ''),  # 移动端URL
                'media_name': item.get('media_name', ''),  # 媒体名称
                'keywords': item.get('keywords', ''),  # 关键词
                'create_time': format_timestamp(item.get('ctime', '')),  # 创建时间
                'update_time': format_timestamp(item.get('mtime', '')),  # 更新时间
                'docid': item.get('docid', ''),  # 文档ID
                'intro': item.get('intro', '')  # 简介
            }
            
            # 提取图片信息
            if 'images' in item and item['images']:
                news_info['images'] = item['images']
            
            result['news_list'].append(news_info)
        
        return result
    
    except requests.exceptions.RequestException as e:
        print(f"请求错误: {e}")
        return None
    except Exception as e:
        print(f"解析错误: {e}")
        import traceback
        print(traceback.format_exc())
        return None


def format_timestamp(timestamp):
    """将时间戳转换为可读格式"""
    if not timestamp:
        return ""
    
    try:
        # 将时间戳转换为可读格式
        return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(timestamp)))
    except:
        return timestamp


def CATEGORY_MAP():
    return {
        "全部": "2509",
        "国内": "2510",
        "国际": "2511",
        "社会": "2669",
        "体育": "2512",
        "娱乐": "2513",
        "军事": "2514",
        "科技": "2515",
        "财经": "2516",
        "股市": "2517",
        "美股": "2518"
    }


def main():
    # 分类映射
    category_map = CATEGORY_MAP()
    print("可选分类:")
    for idx, cat in enumerate(category_map.keys(), 1):
        print(f"{idx}. {cat}")
    try:
        choice = int(input("请输入要爬取的分类编号: "))
        if choice < 1 or choice > len(category_map):
            raise ValueError
        category_name = list(category_map.keys())[choice - 1]
        lid = category_map[category_name]
    except Exception:
        print("输入无效，默认选择'全部'")
        category_name = "全部"
        lid = category_map[category_name]
    # 目标URL
    url = f"https://feed.mix.sina.com.cn/api/roll/get?pageid=153&lid={lid}&k=&num=50&page=1&r={str(time.time()).replace('.', '')}&callback=jQuery111205078716479550882_{int(time.time()*1000)}&_={int(time.time()*1000+1)}"
    print(f"开始爬取新浪新闻API数据: {category_name} 分类 {url}")
    news_data = crawl_sina_news_api(url)
    if news_data:
        # 生成文件名
        filename = f"sina_news_api_{category_name}_{time.strftime('%Y%m%d_%H%M%S')}.json"
        # 保存结果
        txt_file, json_file = save_to_file(news_data, filename)
        print(f"爬取成功!")
        print(f"总新闻数: {news_data['total']}")
        print(f"本次获取: {len(news_data['news_list'])} 条新闻")
        print(f"结果已保存到: {txt_file} 和 {json_file}")
    else:
        print("爬取失败!")


# 定义一个函数来调用Java接口

def call_java_interface(file_name, content_text):
    url = "http://localhost:8081/news/putContent"
    headers = {'Content-Type': 'application/json'}
    data = {
        'fileName': file_name,
        'contentText': content_text
    }
    try:
        response = requests.post(url, json=data, headers=headers)
        content = response.text
        return  content# 假设接口返回JSON数据
    except requests.exceptions.RequestException as e:
        print(f"请求错误: {e}")
        return None

# 在main函数中调用这个接口
if __name__ == "__main__":
    main()